using AgentFrameworkDemo.Models;
using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;

namespace AgentFrameworkDemo.Services;

/// <summary>
/// 工具执行服务
/// 统一管理所有类型的工具执行器
/// </summary>
public interface IToolExecutionService
{
    /// <summary>
    /// 获取所有可用工具
    /// </summary>
    /// <param name="agentId">Agent ID（可选）</param>
    /// <returns>工具定义列表</returns>
    Task<List<ToolDefinition>> GetAllAvailableToolsAsync(string? agentId = null);

    /// <summary>
    /// 执行工具
    /// </summary>
    /// <param name="request">工具执行请求</param>
    /// <returns>工具执行结果</returns>
    Task<ToolExecutionResult> ExecuteToolAsync(ToolExecutionRequest request);

    /// <summary>
    /// 根据输入内容智能选择并执行工具
    /// </summary>
    /// <param name="input">用户输入</param>
    /// <param name="agentId">Agent ID</param>
    /// <param name="sessionId">会话ID</param>
    /// <returns>工具执行结果列表</returns>
    Task<List<ToolExecutionResult>> ExecuteToolsForInputAsync(string input, string agentId, string? sessionId = null);

    /// <summary>
    /// 判断输入是否需要使用工具
    /// </summary>
    /// <param name="input">用户输入</param>
    /// <param name="availableTools">可用工具列表</param>
    /// <returns>是否需要使用工具</returns>
    Task<bool> ShouldUseToolsAsync(string input, List<ToolDefinition> availableTools);

    /// <summary>
    /// 获取工具执行历史
    /// </summary>
    /// <param name="agentId">Agent ID</param>
    /// <param name="limit">限制数量</param>
    /// <returns>执行历史</returns>
    Task<List<ToolExecutionResult>> GetExecutionHistoryAsync(string agentId, int limit = 50);

    /// <summary>
    /// 注册工具执行器
    /// </summary>
    /// <param name="executor">工具执行器</param>
    void RegisterExecutor(IToolExecutor executor);
}

public class ToolExecutionService : IToolExecutionService
{
    private readonly ILogger<ToolExecutionService> _logger;
    private readonly List<IToolExecutor> _executors;
    private readonly ConcurrentDictionary<string, ToolExecutionResult> _executionHistory;
    private readonly ConcurrentDictionary<string, DateTime> _lastToolUsage;

    public ToolExecutionService(ILogger<ToolExecutionService> logger)
    {
        _logger = logger;
        _executors = new List<IToolExecutor>();
        _executionHistory = new ConcurrentDictionary<string, ToolExecutionResult>();
        _lastToolUsage = new ConcurrentDictionary<string, DateTime>();
    }

    public void RegisterExecutor(IToolExecutor executor)
    {
        _executors.Add(executor);
        _logger.LogInformation("Registered tool executor: {ToolType}", executor.ToolType);
    }

    public async Task<List<ToolDefinition>> GetAllAvailableToolsAsync(string? agentId = null)
    {
        var allTools = new List<ToolDefinition>();

        foreach (var executor in _executors)
        {
            try
            {
                var tools = await executor.GetAvailableToolsAsync(agentId);
                allTools.AddRange(tools);
                _logger.LogDebug("Found {Count} tools from executor: {ToolType}", tools.Count, executor.ToolType);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Failed to get tools from executor: {ToolType}", executor.ToolType);
            }
        }

        // 按工具类型和名称排序
        return allTools
            .OrderBy(t => t.Type)
            .ThenBy(t => t.Name)
            .ToList();
    }

    public async Task<ToolExecutionResult> ExecuteToolAsync(ToolExecutionRequest request)
    {
        var executionId = Guid.NewGuid().ToString();
        var startTime = DateTime.UtcNow;

        _logger.LogInformation("Executing tool: {ToolId} for agent: {AgentId}", request.ToolId, request.AgentId);

        try
        {
            // 查找合适的执行器
            var executor = await FindExecutorAsync(request.ToolId);
            if (executor == null)
            {
                return new ToolExecutionResult
                {
                    Success = false,
                    ErrorMessage = $"No executor found for tool: {request.ToolId}",
                    ToolId = request.ToolId,
                    ToolName = "Unknown",
                    ExecutionTime = DateTime.UtcNow - startTime,
                    ToolType = ToolType.Builtin // 默认类型
                };
            }

            // 执行工具
            var result = await executor.ExecuteToolAsync(request);

            // 记录执行历史
            _executionHistory[executionId] = result;
            _lastToolUsage[request.ToolId] = DateTime.UtcNow;

            // 清理旧的历史记录（保持最近1000条）
            if (_executionHistory.Count > 1000)
            {
                var toRemove = _executionHistory.Keys.Take(100).ToList();
                foreach (var key in toRemove)
                {
                    _executionHistory.TryRemove(key, out _);
                }
            }

            _logger.LogInformation("Tool execution completed: {ToolId}, Success: {Success}, Duration: {Duration}ms",
                request.ToolId, result.Success, result.ExecutionTime.TotalMilliseconds);

            return result;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to execute tool: {ToolId}", request.ToolId);

            var errorResult = new ToolExecutionResult
            {
                Success = false,
                ErrorMessage = ex.Message,
                ToolId = request.ToolId,
                ToolName = "Unknown",
                ExecutionTime = DateTime.UtcNow - startTime,
                ToolType = ToolType.Builtin
            };

            _executionHistory[executionId] = errorResult;
            return errorResult;
        }
    }

    public async Task<List<ToolExecutionResult>> ExecuteToolsForInputAsync(string input, string agentId, string? sessionId = null)
    {
        var results = new List<ToolExecutionResult>();

        try
        {
            // 获取所有可用工具
            var availableTools = await GetAllAvailableToolsAsync(agentId);

            // 判断是否需要使用工具
            if (!await ShouldUseToolsAsync(input, availableTools))
            {
                _logger.LogDebug("No tools needed for input: {Input}", input);
                return results;
            }

            // 智能选择工具
            var selectedTools = await SelectToolsForInputAsync(input, availableTools);

            // 并行执行选中的工具
            var tasks = selectedTools.Select(async tool =>
            {
                var request = new ToolExecutionRequest
                {
                    ToolId = tool.Id,
                    Parameters = await ExtractToolParametersAsync(input, tool),
                    AgentId = agentId,
                    SessionId = sessionId,
                    Timeout = TimeSpan.FromSeconds(30)
                };

                return await ExecuteToolAsync(request);
            });

            var toolResults = await Task.WhenAll(tasks);
            results.AddRange(toolResults);

            _logger.LogInformation("Executed {Count} tools for input: {Input}", results.Count, input);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to execute tools for input: {Input}", input);
        }

        return results;
    }

    public async Task<bool> ShouldUseToolsAsync(string input, List<ToolDefinition> availableTools)
    {
        if (!availableTools.Any()) return false;

        var inputLower = input.ToLowerInvariant();

        // 检查明确的关键词
        var toolKeywords = new[]
        {
            "计算", "算", "数学", "加", "减", "乘", "除", "平方", "根",
            "时间", "日期", "几点", "现在", "当前",
            "天气", "气温", "下雨", "晴天",
            "文本", "字符", "长度", "大小写", "分割",
            "查询", "搜索", "找", "获取",
            "转换", "格式", "解析", "处理"
        };

        var hasKeyword = toolKeywords.Any(keyword => inputLower.Contains(keyword));
        if (hasKeyword) return true;

        // 检查是否有特定Agent类型的请求
        var agentToolKeywords = new[]
        {
            "代码", "编程", "developer", "code",
            "教师", "老师", "教学", "解释",
            "分析", "分析师", "数据",
            "助手", "help", "assist"
        };

        var hasAgentToolRequest = agentToolKeywords.Any(keyword => inputLower.Contains(keyword));
        if (hasAgentToolRequest) return true;

        // 检查问题类型
        var questionPatterns = new[]
        {
            "如何", "怎么", "怎样", "帮助我", "请帮我",
            "什么是", "解释", "说明", "介绍",
            "写一个", "创建", "生成", "制作"
        };

        var isQuestion = questionPatterns.Any(pattern => inputLower.Contains(pattern));
        if (isQuestion && availableTools.Any(t => t.Type == ToolType.AgentTool)) return true;

        // 检查是否包含数字表达式
        if (System.Text.RegularExpressions.Regex.IsMatch(input, @"\d+(\s*[\+\-\*\/]\s*\d+)+"))
        {
            return true;
        }

        // 检查是否是日期时间相关请求
        if (inputLower.Contains("现在") || inputLower.Contains("当前") || inputLower.Contains("今天"))
        {
            return true;
        }

        return false;
    }

    public async Task<List<ToolExecutionResult>> GetExecutionHistoryAsync(string agentId, int limit = 50)
    {
        await Task.CompletedTask;

        return _executionHistory.Values
            .Where(r => r.Metadata?.ContainsKey("agentId") == true &&
                       r.Metadata["agentId"]?.ToString() == agentId)
            .OrderByDescending(r => r.ExecutedAt)
            .Take(limit)
            .ToList();
    }

    private async Task<IToolExecutor?> FindExecutorAsync(string toolId)
    {
        foreach (var executor in _executors)
        {
            if (await executor.IsToolAvailableAsync(toolId))
            {
                return executor;
            }
        }
        return null;
    }

    private async Task<List<ToolDefinition>> SelectToolsForInputAsync(string input, List<ToolDefinition> availableTools)
    {
        var selectedTools = new List<ToolDefinition>();
        var inputLower = input.ToLowerInvariant();

        // 根据关键词选择工具
        foreach (var tool in availableTools)
        {
            if (await ShouldSelectToolForInputAsync(inputLower, tool))
            {
                selectedTools.Add(tool);
            }
        }

        // 限制同时执行的工具数量
        return selectedTools.Take(3).ToList();
    }

    private async Task<bool> ShouldSelectToolForInputAsync(string inputLower, ToolDefinition tool)
    {
        await Task.CompletedTask;

        var toolName = tool.Name.ToLowerInvariant();
        var toolDesc = tool.Description.ToLowerInvariant();
        var toolTags = tool.Tags.Select(t => t.ToLowerInvariant()).ToList();

        // 数学工具
        if (tool.Id.Contains("math") || toolName.Contains("数学") || toolName.Contains("计算"))
        {
            return inputLower.Contains("计算") || inputLower.Contains("算") ||
                   System.Text.RegularExpressions.Regex.IsMatch(inputLower, @"\d+");
        }

        // 日期时间工具
        if (tool.Id.Contains("datetime") || tool.Id.Contains("time") || toolName.Contains("时间"))
        {
            return inputLower.Contains("时间") || inputLower.Contains("日期") ||
                   inputLower.Contains("现在") || inputLower.Contains("当前");
        }

        // 文本处理工具
        if (tool.Id.Contains("text") || toolName.Contains("文本"))
        {
            return inputLower.Contains("文本") || inputLower.Contains("字符") ||
                   inputLower.Contains("长度") || inputLower.Contains("大小写");
        }

        // Agent工具
        if (tool.Type == ToolType.AgentTool)
        {
            return toolTags.Any(tag => inputLower.Contains(tag)) ||
                   toolDesc.Any(desc => inputLower.Contains(desc));
        }

        // MCP工具（通常基于描述匹配）
        if (tool.Type == ToolType.McpServer)
        {
            return toolDesc.Split(' ', ',', '，')
                .Any(word => inputLower.Contains(word.ToLowerInvariant()));
        }

        return false;
    }

    private async Task<Dictionary<string, object>> ExtractToolParametersAsync(string input, ToolDefinition tool)
    {
        var parameters = new Dictionary<string, object>();

        // 基本输入参数
        if (tool.Parameters.ContainsKey("input"))
        {
            parameters["input"] = input;
        }

        // 根据工具类型提取特定参数
        switch (tool.Id)
        {
            case "math_calculate":
                var mathExpression = ExtractMathExpression(input);
                if (!string.IsNullOrEmpty(mathExpression))
                {
                    parameters["expression"] = mathExpression;
                }
                break;

            case "text_length":
            case "text_case":
            case "text_split":
                var textToProcess = ExtractTextToProcess(input);
                if (!string.IsNullOrEmpty(textToProcess))
                {
                    parameters["text"] = textToProcess;
                }

                if (tool.Id == "text_case" && input.ToLowerInvariant().Contains("小写"))
                {
                    parameters["target_case"] = "lower";
                }
                else if (tool.Id == "text_case" && input.ToLowerInvariant().Contains("标题"))
                {
                    parameters["target_case"] = "title";
                }
                break;

            case "weather_query":
                var city = ExtractCity(input);
                if (!string.IsNullOrEmpty(city))
                {
                    parameters["city"] = city;
                }
                break;
        }

        await Task.CompletedTask;
        return parameters;
    }

    private string ExtractMathExpression(string input)
    {
        // 简单的数学表达式提取
        var match = System.Text.RegularExpressions.Regex.Match(input, @"([\d\.\s\+\-\*\/\(\)\^]+)");
        return match.Success ? match.Value.Trim() : string.Empty;
    }

    private string ExtractTextToProcess(string input)
    {
        // 提取引号中的文本
        var quoteMatch = System.Text.RegularExpressions.Regex.Match(input, @"['""]([^'""]+)['""]");
        if (quoteMatch.Success)
        {
            return quoteMatch.Groups[1].Value;
        }

        // 提取冒号后的文本
        var colonMatch = System.Text.RegularExpressions.Regex.Match(input, @"[:：]\s*(.+)");
        if (colonMatch.Success)
        {
            return colonMatch.Groups[1].Value.Trim();
        }

        return string.Empty;
    }

    private string ExtractCity(string input)
    {
        // 简单的城市名称提取
        var cities = new[] { "北京", "上海", "广州", "深圳", "杭州", "南京", "武汉", "成都", "西安", "重庆" };
        foreach (var city in cities)
        {
            if (input.Contains(city))
            {
                return city;
            }
        }

        return string.Empty;
    }
}